
class EventEmitter {
    // 定义用来记录事件类型及其事件监听器的实例变量
    events = {
    }
    // 绑定事件
    on( type , handler ){
        // 从 events 对象中尝试获取 type 事件对应的监听器数组
        let arr = this.events[ type ];
        // 若能够得到监听器数组
        if( arr ) {
            // 则将新的监听器添加到数组中
            arr.push( handler );
            return;
        }
        // 若不能得到监听器数组，则添加 type 对应的监听器数组
        this.events[ type ] = [ handler ];
    }
    emit( type , ...params ) {
        // 从 events 对象中尝试获取 type 事件对应的监听器数组
        let arr = this.events[ type ];
        if( arr ) {
            arr.forEach( h => h.call( this , ...params ) );
        }
    }
    off( type , handler ) {
        // 从 events 对象中尝试获取 type 事件对应的监听器数组
        let arr = this.events[ type ];
        if( arr ) {
            // 如果只有一个监听器并且该监听器就是需要删除的监听器
            if( arr.length === 1 && arr[0] === handler ) {
                delete this.events[ type ];
                return;
            }
            let index = arr.findIndex( h => h === handler );
            if( index != -1 ) {
                arr.splice( index , 1 );
            }
        }
    }
}

let x = new EventEmitter();

const type = '开火';
// 在参数列表中的 ...params 表示 REST参数
const handler1 = function(...params){
    // 在 log 参数中的 ...params 表示 展开运算符
    console.log('handler1 开火: ' , ...params);
}

// 绑定事件监听器
x.on( type , handler1 );

const handler2 = function(...params){
    console.log('handler2 开火: ' , ...params);
}

// 绑定事件监听器
x.on( type , handler2 );

// 触发事件
x.emit( type , '小日本' , '美利坚' , '德意志' , '法兰西' );

// 移除事件监听器
x.off( type , handler2 );

x.emit( type , '狗汉奸' , '狗腿子' , '卖国贼' , '洋买办' );

x.off( type , handler1 );

x.emit( type , '公知' );